home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / animutil / pvquan / giflib / dgif_lib.c next >
Encoding:
C/C++ Source or Header  |  1992-11-30  |  18.4 KB  |  495 lines

  1. /************************************************************************
  2.  *                                                                      *
  3.  *                  Copyright (c) 1991, Frank van der Hulst             *
  4.  *                          All Rights Reserved                         *
  5.  *                                                                      *
  6.  * Authors:                                                             *
  7.  *        FvdH - Frank van der Hulst (Wellington, NZ)                   *
  8.  *                                                                      *
  9.  * Versions:                                                            *
  10.  *      V1.1 910626 FvdH - QUANT released for DBW_RENDER                *
  11.  *      V1.2 911021 FvdH - QUANT released for PoV Ray                   *
  12.  *      V1.4 920303 FvdH - Ported to GNU                                *
  13.  *      V1.6 921022 FvdH - Ported to OS/2                               *
  14.  *                                                                      *
  15.  ************************************************************************/
  16. /******************************************************************************
  17. *   "Gif-Lib" - Yet another gif library.                      *
  18. *                                          *
  19. * Written by:  Gershon Elber            IBM PC Ver 1.1,    Aug. 1990     *
  20. *******************************************************************************
  21. * The kernel of the GIF Decoding process can be found here.              *
  22. *******************************************************************************
  23. * History:                                      *
  24. * 16 Jun 89 - Version 1.0 by Gershon Elber.                      *
  25. *  3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). *
  26. ******************************************************************************/
  27.  
  28.  
  29. #include <stdlib.h>
  30. #ifdef __TURBOC__
  31. #include <io.h>
  32. #include <alloc.h>
  33. #include <sys\stat.h>
  34. #endif
  35.  
  36. #include <fcntl.h>
  37. #include <string.h>
  38.  
  39. #include "gif_lib.h"
  40. #include "gif_hash.h"
  41.  
  42. #define LZ_MAX_CODE    4095        /* Biggest code possible in 12 bits. */
  43. #define LZ_BITS        12
  44.  
  45. #define GIF_STAMP_LEN    sizeof(GIF_STAMP) - 1
  46. #define GIF_STAMP    "GIFVER"     /* First chars in file - GIF stamp. */
  47. #define GIF_VERSION_POS    3        /* Version first character in stamp. */
  48.  
  49. #define NO_SUCH_CODE        4098    /* Impossible code, to signal empty. */
  50.  
  51. #define RED        0
  52. #define GREEN    1
  53. #define BLUE    2
  54.  
  55. static int
  56.     priv_BitsPerPixel,        /* Bits per pixel (Codes uses at list this + 1). */
  57.     priv_ClearCode,                       /* The CLEAR LZ code. */
  58.     priv_EOFCode,                         /* The EOF LZ code. */
  59.     priv_RunningCode,            /* The next code algorithm can generate. */
  60.     priv_RunningBits,/* The number of bits required to represent RunningCode. */
  61.     priv_MaxCode1,  /* 1 bigger than max. possible code, in RunningBits bits. */
  62.     priv_LastCode,                /* The code before the current code. */
  63.     priv_StackPtr,                 /* For character stack (see below). */
  64.     priv_CrntShiftState;                /* Number of bits in CrntShiftDWord. */
  65. static     unsigned long priv_CrntShiftDWord,     /* For bytes decomposition into codes. */
  66.           priv_PixelCount;               /* Number of pixels in image. */
  67. static     FILE *priv_File;                          /* File as stream. */
  68. static     GifByteType priv_Buf[256];           /* Compressed input is buffered here. */
  69. static     GifByteType priv_Stack[LZ_MAX_CODE];     /* Decoded pixels are stacked here. */
  70. static     GifByteType priv_Suffix[LZ_MAX_CODE+1];           /* So we can trace the codes. */
  71. static     unsigned int priv_Prefix[LZ_MAX_CODE+1];
  72.  
  73. static int DGifDecompressLine(GifPixelType *Line, int LineLen);
  74. static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode);
  75. static int DGifDecompressInput(int *Code);
  76. static int DGifBufferedInput(FILE *File, GifByteType *Buf, unsigned char *NextByte);
  77. static int DGifGetCodeNext(GifByteType **CodeBlock);
  78.  
  79. #ifndef __TURBOC__
  80. int getw(FILE *fp)
  81. {
  82.     int temp;
  83.     temp = getc(fp);
  84.     temp = getc(fp) * 0x100 + temp;
  85.     return temp;
  86. }
  87. #endif
  88.  
  89. /******************************************************************************
  90. *   Open a new gif file for read, given by its name.                  *
  91. *   Returns GifFileType pointer dynamically allocated which serves as the gif *
  92. * info record. _GifError is cleared if succesfull.                  *
  93. ******************************************************************************/
  94. FILE *DGifOpenFile(char *name)
  95. {
  96.     char Buf[GIF_STAMP_LEN+1];
  97.  
  98.     if ((priv_File = fopen(name, "rb")) == NULL) return NULL;
  99.  
  100.     /* Lets see if this is GIF file: */
  101.     if (fread(Buf, 1, GIF_STAMP_LEN, priv_File) != GIF_STAMP_LEN) {
  102.         return NULL;
  103.     }
  104.  
  105.     /* The GIF Version number is ignored at this time. Maybe we should do    */
  106.     /* something more useful with it.                         */
  107.     Buf[GIF_STAMP_LEN] = 0;
  108.     if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) return NULL;
  109.     return priv_File;
  110. }
  111.  
  112. /******************************************************************************
  113. *   This routine should be called before any other DGif calls. Note that      *
  114. * this routine is called automatically from DGif file open routines.          *
  115. ******************************************************************************/
  116. void DGifGetScreenDesc(int *Width, int *Height, int *ColorRes, int *BackGround,
  117.     int *BitsPerPixel, unsigned char *palette)
  118. {
  119.     int i, Size;
  120.     char Buf;
  121.  
  122.     /* Put the screen descriptor into the file: */
  123.     *Width = getw(priv_File);
  124.     *Height = getw(priv_File);
  125.  
  126.     Buf = fgetc(priv_File);
  127.     *ColorRes = (((Buf & 0x70) + 1) >> 4) + 1;
  128.     *BitsPerPixel = (Buf & 0x07) + 1;
  129.     *BackGround = fgetc(priv_File);
  130.     fgetc(priv_File);
  131.     if (Buf & 0x80) {             /* Do we have global color map? */
  132.         Size = (1 << *BitsPerPixel) * 3;
  133.         /* Get the global color map: */
  134.         for (i = 0; i < Size; i += 3) {
  135.             Buf = getc(priv_File);
  136.             palette[i+RED]   = Buf /*getc(priv_File)*/ >> (8 - *ColorRes);
  137.             palette[i+GREEN] = getc(priv_File) >> (8 - *ColorRes);
  138.             palette[i+BLUE]  = getc(priv_File) >> (8 - *ColorRes);
  139.         }
  140.     }
  141. }
  142.  
  143. /******************************************************************************
  144. *   This routine should be called before any attemp to read an image.         *
  145. ******************************************************************************/
  146. int DGifGetRecordType(GifRecordType *Type)
  147. {
  148.     GifByteType Buf;
  149.  
  150.     if (fread(&Buf, 1, 1, priv_File) != 1) {
  151.     return GIF_ERROR;
  152.     }
  153.  
  154.     switch (Buf) {
  155.     case ',':
  156.         *Type = IMAGE_DESC_RECORD_TYPE;
  157.         break;
  158.     case '!':
  159.         *Type = EXTENSION_RECORD_TYPE;
  160.         break;
  161.     case ';':
  162.         *Type = TERMINATE_RECORD_TYPE;
  163.         break;
  164.     default:
  165.         *Type = UNDEFINED_RECORD_TYPE;
  166.         return GIF_ERROR;
  167.     }
  168.  
  169.     return GIF_OK;
  170. }
  171.  
  172. /******************************************************************************
  173. *   This routine should be called before any attemp to read an image.         *
  174. *   Note it is assumed the Image desc. header (',') has been read.          *
  175. ******************************************************************************/
  176. void     DGifGetImageDesc(unsigned int *Left, unsigned int *Top, unsigned int *Width, unsigned int *Height, unsigned char *palette)
  177. {
  178.     int Size, i;
  179.     int ColorRes, BitsPerPixel;
  180.     char Buf;
  181.  
  182.     *Left   = getw(priv_File);
  183.     *Top    = getw(priv_File);
  184.     *Width  = getw(priv_File);
  185.     *Height = getw(priv_File);
  186.     Buf = fgetc(priv_File);
  187.     ColorRes = (((Buf & 0x70) + 1) >> 4) + 1;
  188.     BitsPerPixel = (Buf & 0x07) + 1;
  189.     if (Buf & 0x80) {        /* Does this image have local color map? */
  190.         Size = (1 << BitsPerPixel) * 3;
  191.         /* Get the image local color map: */
  192.         for (i = 0; i < Size; i += 3) {
  193.             palette[i+RED]   = getc(priv_File) >> (8 - ColorRes);
  194.             palette[i+GREEN] = getc(priv_File) >> (8 - ColorRes);
  195.             palette[i+BLUE]  = getc(priv_File) >> (8 - ColorRes);
  196.         }
  197.     }
  198.  
  199.     DGifSetupDecompress((long) *Width * (long) *Height);  /* Reset decompress algorithm parameters. */
  200. }
  201.  
  202. /******************************************************************************
  203. *  Get one full scanned line (Line) of length LineLen from GIF file.          *
  204. ******************************************************************************/
  205. int DGifGetLine(GifPixelType *Line, int LineLen)
  206. {
  207.     GifByteType *Dummy;
  208.  
  209.     if ((priv_PixelCount -= LineLen) < 0)     return GIF_ERROR;
  210.  
  211.     if (DGifDecompressLine(Line, LineLen) != GIF_OK) return GIF_ERROR;
  212.     if (priv_PixelCount == 0) {
  213.         /* We probably would not be called any more, so lets clean          */
  214.         /* everything before we return: need to flush out all rest of    */
  215.         /* image until empty block (size 0) detected. We use GetCodeNext.*/
  216.         do if (DGifGetCodeNext(&Dummy) == GIF_ERROR) return GIF_ERROR;
  217.         while (Dummy != NULL);
  218.     }
  219.     return GIF_OK;
  220. }
  221.  
  222. /******************************************************************************
  223. *   This routine should be called last, to close GIF file.              *
  224. ******************************************************************************/
  225. void DGifCloseFile(void)
  226. {
  227.      fclose(priv_File);
  228. }
  229.  
  230. /******************************************************************************
  231. *   Continue to get the image code in compressed form. This routine should be *
  232. * called until NULL block is returned.                          *
  233. *   The block should NOT be freed by the user (not dynamically allocated).    *
  234. ******************************************************************************/
  235. static int DGifGetCodeNext(GifByteType **CodeBlock)
  236. {
  237.     GifByteType Buf;
  238.  
  239.      if (fread(&Buf, 1, 1, priv_File) != 1)     return GIF_ERROR;
  240.  
  241.     if (Buf > 0) {
  242.     *CodeBlock = priv_Buf;           /* Use private unused buffer. */
  243.     (*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
  244.     if (fread(&((*CodeBlock)[1]), 1, Buf, priv_File) != Buf)     return GIF_ERROR;
  245.     }
  246.     else {
  247.     *CodeBlock = NULL;
  248.     priv_Buf[0] = 0;           /* Make sure the buffer is empty! */
  249.     priv_PixelCount = 0;   /* And local info. indicate image read. */
  250.     }
  251.  
  252.     return GIF_OK;
  253. }
  254.  
  255. /******************************************************************************
  256. *   Setup the LZ decompression for this image:                      *
  257. ******************************************************************************/
  258. void DGifSetupDecompress(long size)
  259. {
  260.     int i, BitsPerPixel;
  261.     GifByteType CodeSize;
  262.     unsigned int *Prefix;
  263.  
  264.     priv_PixelCount = size;
  265.  
  266.     fread(&CodeSize, 1, 1, priv_File);    /* Read Code size from file. */
  267.     BitsPerPixel = CodeSize;
  268.  
  269.     priv_Buf[0] = 0;                  /* Input Buffer empty. */
  270.     priv_BitsPerPixel = BitsPerPixel;
  271.     priv_ClearCode = (1 << BitsPerPixel);
  272.     priv_EOFCode = priv_ClearCode + 1;
  273.     priv_RunningCode = priv_EOFCode + 1;
  274.     priv_RunningBits = BitsPerPixel + 1;     /* Number of bits per code. */
  275.     priv_MaxCode1 = 1 << priv_RunningBits;     /* Max. code + 1. */
  276.     priv_StackPtr = 0;            /* No pixels on the pixel stack. */
  277.     priv_LastCode = NO_SUCH_CODE;
  278.     priv_CrntShiftState = 0;    /* No information in CrntShiftDWord. */
  279.     priv_CrntShiftDWord = 0;
  280.  
  281.     Prefix = priv_Prefix;
  282.     for (i = 0; i < LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE;
  283. }
  284.  
  285. /******************************************************************************
  286. *   The LZ decompression routine:                          *
  287. *   This version decompress the given gif file into Line of length LineLen.   *
  288. *   This routine can be called few times (one per scan line, for example), in *
  289. * order the complete the whole image.                          *
  290. ******************************************************************************/
  291. static int DGifDecompressLine(GifPixelType *Line, int LineLen)
  292. {
  293.     int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
  294.     GifByteType *Stack, *Suffix;
  295.     unsigned int *Prefix;
  296.  
  297.     StackPtr = priv_StackPtr;
  298.     Prefix = priv_Prefix;
  299.     Suffix = priv_Suffix;
  300.     Stack = priv_Stack;
  301.     EOFCode = priv_EOFCode;
  302.     ClearCode = priv_ClearCode;
  303.     LastCode = priv_LastCode;
  304.  
  305.     if (StackPtr != 0) {
  306.     /* Let pop the stack off before continueing to read the gif file: */
  307.     while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
  308.     }
  309.  
  310.     while (i < LineLen) {                /* Decode LineLen items. */
  311.     if (DGifDecompressInput(&CrntCode) == GIF_ERROR)
  312.             return GIF_ERROR;
  313.  
  314.     if (CrntCode == EOFCode) {
  315.         /* Note however that usually we will not be here as we will stop */
  316.         /* decoding as soon as we got all the pixel, or EOF code will    */
  317.         /* not be read at all, and DGifGetLine/Pixel clean everything.   */
  318.         if (i != LineLen - 1 || priv_PixelCount != 0) {
  319.         return GIF_ERROR;
  320.         }
  321.         i++;
  322.     }
  323.     else if (CrntCode == ClearCode) {
  324.         /* We need to start over again: */
  325.         for (j = 0; j < LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
  326.         priv_RunningCode = priv_EOFCode + 1;
  327.         priv_RunningBits = priv_BitsPerPixel + 1;
  328.         priv_MaxCode1 = 1 << priv_RunningBits;
  329.         LastCode = priv_LastCode = NO_SUCH_CODE;
  330.     }
  331.     else {
  332.         /* Its regular code - if in pixel range simply add it to output  */
  333.         /* stream, otherwise trace to codes linked list until the prefix */
  334.         /* is in pixel range:                         */
  335.         if (CrntCode < ClearCode) {
  336.         /* This is simple - its pixel scalar, so add it to output:   */
  337.         Line[i++] = CrntCode;
  338.         }
  339.         else {
  340.         /* Its a code to needed to be traced: trace the linked list  */
  341.         /* until the prefix is a pixel, while pushing the suffix     */
  342.         /* pixels on our stack. If we done, pop the stack in reverse */
  343.         /* (thats what stack is good for!) order to output.         */
  344.         if (Prefix[CrntCode] == NO_SUCH_CODE) {
  345.             /* Only allowed if CrntCode is exactly the running code: */
  346.             /* In that case CrntCode = XXXCode, CrntCode or the         */
  347.             /* prefix code is last code and the suffix char is         */
  348.             /* exactly the prefix of last code!                 */
  349.             if (CrntCode == priv_RunningCode - 2) {
  350.             CrntPrefix = LastCode;
  351.             Suffix[priv_RunningCode - 2] =
  352.             Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
  353.                             LastCode, ClearCode);
  354.             }
  355.             else {
  356.             return GIF_ERROR;
  357.             }
  358.         }
  359.         else
  360.             CrntPrefix = CrntCode;
  361.  
  362.         /* Now (if image is O.K.) we should not get and NO_SUCH_CODE */
  363.         /* During the trace. As we might loop forever, in case of    */
  364.         /* defective image, we count the number of loops we trace    */
  365.         /* and stop if we got LZ_MAX_CODE. obviously we can not      */
  366.         /* loop more than that.                         */
  367.         j = 0;
  368.         while (j++ <= LZ_MAX_CODE &&
  369.                CrntPrefix > ClearCode &&
  370.                CrntPrefix <= LZ_MAX_CODE) {
  371.             Stack[StackPtr++] =    Suffix[CrntPrefix];
  372.             CrntPrefix = Prefix[CrntPrefix];
  373.         }
  374.         if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
  375.             return GIF_ERROR;
  376.         }
  377.         /* Push the last character on stack: */
  378.         Stack[StackPtr++] = CrntPrefix;
  379.  
  380.         /* Now lets pop all the stack into output: */
  381.         while (StackPtr != 0 && i < LineLen)
  382.             Line[i++] = Stack[--StackPtr];
  383.         }
  384.         if (LastCode != NO_SUCH_CODE) {
  385.         Prefix[priv_RunningCode - 2] = LastCode;
  386.  
  387.         if (CrntCode == priv_RunningCode - 2) {
  388.             /* Only allowed if CrntCode is exactly the running code: */
  389.             /* In that case CrntCode = XXXCode, CrntCode or the         */
  390.             /* prefix code is last code and the suffix char is         */
  391.             /* exactly the prefix of last code!                 */
  392.             Suffix[priv_RunningCode - 2] =
  393.             DGifGetPrefixChar(Prefix, LastCode, ClearCode);
  394.         }
  395.         else {
  396.             Suffix[priv_RunningCode - 2] =
  397.             DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
  398.         }
  399.         }
  400.         LastCode = CrntCode;
  401.     }
  402.     }
  403.  
  404.     priv_LastCode = LastCode;
  405.     priv_StackPtr = StackPtr;
  406.  
  407.     return GIF_OK;
  408. }
  409.  
  410. /******************************************************************************
  411. * Routine to trace the Prefixes linked list until we get a prefix which is    *
  412. * not code, but a pixel value (less than ClearCode). Returns that pixel value.*
  413. * If image is defective, we might loop here forever, so we limit the loops to *
  414. * the maximum possible if image O.k. - LZ_MAX_CODE times.              *
  415. ******************************************************************************/
  416. static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode)
  417. {
  418.     int i = 0;
  419.  
  420.     while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
  421.     return Code;
  422. }
  423.  
  424. /******************************************************************************
  425. *   The LZ decompression input routine:                          *
  426. *   This routine is responsable for the decompression of the bit stream from  *
  427. * 8 bits (bytes) packets, into the real codes.                      *
  428. *   Returns GIF_OK if read succesfully.                          *
  429. ******************************************************************************/
  430. static int DGifDecompressInput(int *Code)
  431. {
  432.     GifByteType NextByte;
  433.     static unsigned int CodeMasks[] = {
  434.     0x0000, 0x0001, 0x0003, 0x0007,
  435.     0x000f, 0x001f, 0x003f, 0x007f,
  436.     0x00ff, 0x01ff, 0x03ff, 0x07ff,
  437.     0x0fff
  438.     };
  439.  
  440.     while (priv_CrntShiftState < priv_RunningBits) {
  441.     /* Needs to get more bytes from input stream for next code: */
  442.     if (DGifBufferedInput(priv_File, priv_Buf, &NextByte)
  443.         == GIF_ERROR) {
  444.         return GIF_ERROR;
  445.     }
  446.     priv_CrntShiftDWord |=
  447.         ((unsigned long) NextByte) << priv_CrntShiftState;
  448.     priv_CrntShiftState += 8;
  449.     }
  450.      *Code = (int) priv_CrntShiftDWord & CodeMasks[priv_RunningBits];
  451.  
  452.     priv_CrntShiftDWord >>= priv_RunningBits;
  453.     priv_CrntShiftState -= priv_RunningBits;
  454.  
  455.     /* If code cannt fit into RunningBits bits, must raise its size. Note */
  456.     /* however that codes above 4095 are used for special signaling.      */
  457.     if (++priv_RunningCode > priv_MaxCode1 &&
  458.     priv_RunningBits < LZ_BITS) {
  459.     priv_MaxCode1 <<= 1;
  460.     priv_RunningBits++;
  461.     }
  462.     return GIF_OK;
  463. }
  464.  
  465. /******************************************************************************
  466. *   This routines read one gif data block at a time and buffers it internally *
  467. * so that the decompression routine could access it.                  *
  468. *   The routine returns the next byte from its internal buffer (or read next  *
  469. * block in if buffer empty) and returns GIF_OK if succesful.              *
  470. ******************************************************************************/
  471. static int DGifBufferedInput(FILE *File, GifByteType *Buf,
  472.                               GifByteType *NextByte)
  473. {
  474.     if (Buf[0] == 0) {
  475.     /* Needs to read the next buffer - this one is empty: */
  476.     if (fread(Buf, 1, 1, File) != 1)
  477.     {
  478.         return GIF_ERROR;
  479.     }
  480.     if (fread(&Buf[1], 1, Buf[0], File) != Buf[0])
  481.     {
  482.         return GIF_ERROR;
  483.     }
  484.     *NextByte = Buf[1];
  485.     Buf[1] = 2;       /* We use now the second place as last char read! */
  486.     Buf[0]--;
  487.     }
  488.     else {
  489.     *NextByte = Buf[Buf[1]++];
  490.     Buf[0]--;
  491.     }
  492.  
  493.     return GIF_OK;
  494. }
  495.